
#include "string.h"
#include "optiga_host.h"
#include "optiga_curve.h"
static UBYTE hash_buf[32];
static optiga_odc _odc;
// validate odc_buf, if successful, return a odc pointer
BOOL optiga_hst_verify_odc (optiga_session   *session, UBYTE *odc_buf)
{
	optiga_odc *cert_ptr = &_odc;
	
    session->state=0;   
    memset ((void*)cert_ptr,0,sizeof(_odc));
	
    // copy chip public key
	memcpy ((UBYTE*)cert_ptr->chip_pub_key, &odc_buf[OPTIGA_ODC_PK_OFFSET],
			OPTIGA_KEY_BYTE_LEN+1);
    
    // copy odc's ecdsa s-value
	memcpy ((UBYTE*)cert_ptr->sig.s_value, &odc_buf[OPTIGA_ODC_SVAL_OFFSET],
			OPTIGA_ECDSA_SVAL_LEN);
	
    // copy odc's ecdsa r-value
	memcpy ((UBYTE*)cert_ptr->sig.r_value, odc_buf,OPTIGA_ECDSA_RVAL_LEN);
    
    memcpy (hash_buf, cert_ptr->chip_pub_key, OPTIGA_KEY_BYTE_LEN+1);
    memcpy (&hash_buf[OPTIGA_KEY_BYTE_LEN+1], &(session->chip_id), sizeof(optiga_uid));
	if (optiga_crypto_ecdsa_cert_validate (cert_ptr, hash_buf, sizeof(hash_buf),
										   issuerPubKey)==TRUE)
	{
		cert_ptr->chip_pub_key[5] &= 0x07;  // only keep last 3 bits
        session->cert_ptr = cert_ptr;        
		return TRUE;
	} else
		return FALSE;
}

void optiga_hst_rand_init (uint16_t seed)
{
    optiga_crypto_rand_init (seed);
}

void optiga_hst_session_init (optiga_session *session, optiga_uid *id)
{
    memset (session,0,sizeof(optiga_session));
    memcpy (&(session->chip_id), id, sizeof(optiga_uid));
    session->cert_ptr = (optiga_odc*)0;
    session->state = 0;
}

BOOL optiga_hst_gen_challenge (optiga_session *session)
{
    uint32_t   *ch_ptr = session->challenge;
	
    session->state = 1;
    optiga_crypto_gen_lambda (session->lambda);
    return optiga_crypto_gen_ecc_challenge (session->lambda, ch_ptr);
}



BOOL optiga_hst_verify_response (optiga_session *session, UBYTE *rsp, UBYTE *mac)
{
    mac_t mac_out, mac_to_cmp;
    BOOL  ret;
    memset ((UBYTE*)(session->z_resp),0,sizeof(dwordvec_t));
    memcpy ((UBYTE*)(session->z_resp),rsp,OPTIGA_RESPONSE_LEN);
    memset ((UBYTE*)mac_to_cmp,0,sizeof(mac_to_cmp));
    memcpy ((UBYTE*)mac_to_cmp,mac,OPTIGA_MAC_VALUE_LEN);
    
    if (session->state!=1)
        return FALSE;
    if (optiga_crypto_gen_checkvalue (session->lambda,
                                      session->cert_ptr->chip_pub_key, 
                                      session->checkvalue
                                        )==FALSE) {
        return FALSE;
    }

    ret = optiga_hst_verify_mac (session, 
                                 (UBYTE*)(session->cert_ptr->chip_pub_key),
                                 mac_to_cmp, mac_out);

    
    if (ret) {        
        session->state = 2;
	    return TRUE;	        
    } else {
        return FALSE;
    }
}


BOOL optiga_hst_verify_mac (
  optiga_session *session, 
  UBYTE          *mac_data,
  mac_t          mac_value,
  mac_t          mac_output)
{
    dwordvec_t skey;
    int32_t    t;
    
    if (optiga_crypto_gen_session_key (session->checkvalue, 
                                       session->z_resp,
                                       skey)==FALSE)
        return FALSE;    
   
    mac_algorithm_80(mac_output, (uint32_t*)mac_data, skey);
    
	t = mac_output[0] ^ mac_value[0];
	t |= mac_output[1] ^ mac_value[1];
	t |= mac_output[2] ^ mac_value[2];
    if (t)
		return FALSE;
	else
	    return TRUE;    
}
